using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;

namespace SimplePoker.Main
{
    public class SimpleGeneticPlayer : PlayerBase
    {
        public int FitnessRating { get; set; }
        public int Generation
        {
            get
            {
                return _Generation;
            }
        }
        private int _Generation;
        private Random _Random = new Random();
        Dictionary<int, PlayerAction> _Strategy = new Dictionary<int, PlayerAction>();

        public SimpleGeneticPlayer(string name, int generation, Dictionary<int, PlayerAction> strategy)
            : base(name)
        {
            _Strategy = strategy;
            _Generation = generation;
        }

        public SimpleGeneticPlayer(string name, string dna)
            : base(name)
        {
            ParseDNA(dna);
        }

        public SimpleGeneticPlayer(string name) :base (name)
        {
            for (int i = 1; i < 14; i++)
            {
                _Strategy[i] = RandomAction();   
            }
        }

        private void ParseDNA(string dna)
        {
            var elements = dna.Split(',');

            if (elements.Count() != 13)
                throw new ArgumentException("expected 13 rules in dna");

            foreach (var element in elements)
            {
                ParseDNAElement(element);
            }

        }

        private void ParseDNAElement(string element)
        {
            string actionText = element.Substring(element.Length - 1, 1);
            string rankText = element.Substring(0, element.Length - 1);

            PlayerAction action;
            switch (actionText)
            {
                case "F": action = PlayerAction.FOLD; break;
                case "C": action = PlayerAction.CALL; break;
                case "B": action = PlayerAction.BET; break;
                default: throw new ArgumentException("Unknown action in DNA.");
            }

            int rank = Convert.ToInt32(rankText);

            _Strategy.Add(rank, action);
        }

        public override PlayerAction GetAction()
        {
            return _Strategy[Card.Rank];
        }

        public string GetDNA()
        {
            return _Strategy.ToDNAString();
        }

        public SimpleGeneticPlayer Mate(SimpleGeneticPlayer mate)
        {
            var mateStrategy = mate.GetStrategy();
            var childStrategy = new Dictionary<int, PlayerAction>();
            for (int i = 1; i < 14; i++)
            {
                if (Mutate())
                    childStrategy.Add(i, RandomAction());
                else
                {
                    if (UseOwn())
                        childStrategy.Add(i, _Strategy[i]);
                    else
                        childStrategy.Add(i, mateStrategy[i]);
                }
            }
            int generation = Math.Max(_Generation, mate.Generation) + 1;
            return new SimpleGeneticPlayer("SimpleGeneticPlayer", generation, childStrategy);
        }

        private bool UseOwn()
        {
            return (_Random.Next(0, 2) == 1);
        }

        private PlayerAction RandomAction()
        {
            var random = _Random.Next(0, 3);

            if (random == 0)
                return PlayerAction.FOLD;
            else if (random == 1)
                return PlayerAction.BET;
            else
                return PlayerAction.CALL;
        }


        private bool Mutate()
        {
            var random = new Random();
            return (random.Next(0, 10) == 5);
        }

        private Dictionary<int, PlayerAction> GetStrategy()
        {
            return _Strategy;
        }

        public override string ToString()
        {
            return Name + " Generation: " + _Generation + " [Chip Count : " + ChipCount + "]";
        }


        public override void NotifyOpponentsAction(PlayerAction action)
        {
        }

        public override void ShowOpponentsCard(Card card)
        {
        }

        public override void NotifyNewHand()
        {
        }
    }
}
